#!/bin/bash

# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: database-controller-sts
spec:
  selector:
    matchLabels:
      app: database-controller
  serviceName: database-controller
  replicas: 1
  template:
    metadata:
      labels:
        app: database-controller
    spec:
      serviceAccountName: database-controller-account
      hostNetwork: true
      initContainers:
      - name: database-initializer
        image: {{ cluster_cfg["cluster"]["docker-registry"]["prefix"] }}database-controller:{{ cluster_cfg["cluster"]["docker-registry"]["tag"] }}
        imagePullPolicy: Always
        env:
        # Log level of all logs. You can choose from error, warn, info, http, verbose, debug, and silly. Default value is info.
        - name: LOG_LEVEL
          value: "{{ cluster_cfg['database-controller']['log-level'] }}"
        # The global timeout for all calls to Kubernetes API server. Default value is 120.
        - name: K8S_CONNECTION_TIMEOUT_SECOND
          value: "{{ cluster_cfg['database-controller']['k8s-connection-timeout-second'] }}"
        # The timeout for calls to write merger. Default value is 120.
        - name: WRITE_MERGER_CONNECTION_TIMEOUT_SECOND
          value: "{{ cluster_cfg['database-controller']['write-merger-connection-timeout-second'] }}"
        # Whether to enable retain mode.
        # If someone submits a framework directly without accessing database, we can find the framework in write merger.
        # For these frameworks, if retain mode is on, we will ignore them.
        # If retain mode is off (it is the default setting), we will delete the frameworks to maintain ground-truth in database.
        - name: RETAIN_MODE_ENABLED
{% if cluster_cfg['database-controller']['retain-mode'] %}
          value: "true"
{% else %}
          value: "false"
{% endif %}
         # If RBAC is set up in current environment.
         # If RBAC_IN_CLUSTER=true, the API Server client can read all settings automatically in container.
         # If RBAC_IN_CLUSTER=false, we should set CUSTOM_K8S_API_SERVER_URL.
{% if cluster_cfg['cluster']['common']['k8s-rbac'] != 'false' %}
        - name: RBAC_IN_CLUSTER
          value: "true"
{% else %}
        - name: RBAC_IN_CLUSTER
          value: "false"
        - name: CUSTOM_K8S_API_SERVER_URL
          value: {{ cluster_cfg['layout']['kubernetes']['api-servers-url'] }}
{% endif %}
        # The database client string. It follows the format "<database type>://<user>:<password>@<host>:<port>/<database name>"
        - name: DB_CONNECTION_STR
          value: "{{ cluster_cfg['postgresql']['connection-str'] }}"
        command: ["node", "--max-old-space-size=8192", "initializer/index.js"]
      containers:
      - name: write-merger
        image: {{ cluster_cfg["cluster"]["docker-registry"]["prefix"] }}database-controller:{{ cluster_cfg["cluster"]["docker-registry"]["tag"] }}
        imagePullPolicy: Always
        env:
        # Log level of all logs. You can choose from error, warn, info, http, verbose, debug, and silly. Default value is info.
        - name: LOG_LEVEL
          value: "{{ cluster_cfg['database-controller']['log-level'] }}"
        # The global timeout for all calls to Kubernetes API server. Default value is 120.
        - name: K8S_CONNECTION_TIMEOUT_SECOND
          value: "{{ cluster_cfg['database-controller']['k8s-connection-timeout-second'] }}"
        # The timeout for calls to write merger. Default value is 120.
        - name: WRITE_MERGER_CONNECTION_TIMEOUT_SECOND
          value: "{{ cluster_cfg['database-controller']['write-merger-connection-timeout-second'] }}"
        # Whether to enable retain mode.
        # If someone submits a framework directly without accessing database, we can find the framework in write merger.
        # For these frameworks, if retain mode is on, we will ignore them.
        # If retain mode is off (it is the default setting), we will delete the frameworks to maintain ground-truth in database.
        - name: RETAIN_MODE_ENABLED
{% if cluster_cfg['database-controller']['retain-mode'] %}
          value: "true"
{% else %}
          value: "false"
{% endif %}
         # If RBAC is set up in current environment.
         # If RBAC_IN_CLUSTER=true, the API Server client can read all settings automatically in container.
         # If RBAC_IN_CLUSTER=false, we should set CUSTOM_K8S_API_SERVER_URL.
{% if cluster_cfg['cluster']['common']['k8s-rbac'] != 'false' %}
        - name: RBAC_IN_CLUSTER
          value: "true"
{% else %}
        - name: RBAC_IN_CLUSTER
          value: "false"
        - name: CUSTOM_K8S_API_SERVER_URL
          value: {{ cluster_cfg['layout']['kubernetes']['api-servers-url'] }}
{% endif %}
        # The database client string. It follows the format "<database type>://<user>:<password>@<host>:<port>/<database name>"
        - name: DB_CONNECTION_STR
          value: "{{ cluster_cfg['postgresql']['connection-str'] }}"
        # Max connection number to database in write merger. Default value is 50.
        - name: MAX_DB_CONNECTION
          value: "{{ cluster_cfg['database-controller']['write-merger-max-db-connection'] }}"
        # The serving port for write merger.
        - name: PORT
          value: "{{ cluster_cfg['database-controller']['write-merger-port'] }}"
        readinessProbe:
          httpGet:
            path: /api/v1/ping
            port: {{ cluster_cfg['database-controller']['write-merger-port'] }}
        livenessProbe:
          httpGet:
            path: /api/v1/ping
            port: {{ cluster_cfg['database-controller']['write-merger-port'] }}
          initialDelaySeconds: 60
          periodSeconds: 60
        command: ["node", "--max-old-space-size={{ cluster_cfg['database-controller']['write-merger-max-heap-mb'] }}", "write-merger/index.js"]
      - name: framework-watcher
        image: {{ cluster_cfg["cluster"]["docker-registry"]["prefix"] }}database-controller:{{ cluster_cfg["cluster"]["docker-registry"]["tag"] }}
        imagePullPolicy: Always
        env:
        # Log level of all logs. You can choose from error, warn, info, http, verbose, debug, and silly. Default value is info.
        - name: LOG_LEVEL
          value: "{{ cluster_cfg['database-controller']['log-level'] }}"
        # The global timeout for all calls to Kubernetes API server. Default value is 120.
        - name: K8S_CONNECTION_TIMEOUT_SECOND
          value: "{{ cluster_cfg['database-controller']['k8s-connection-timeout-second'] }}"
        # The timeout for calls to write merger. Default value is 120.
        - name: WRITE_MERGER_CONNECTION_TIMEOUT_SECOND
          value: "{{ cluster_cfg['database-controller']['write-merger-connection-timeout-second'] }}"
        # Whether to enable retain mode.
        # If someone submits a framework directly without accessing database, we can find the framework in write merger.
        # For these frameworks, if retain mode is on, we will ignore them.
        # If retain mode is off (it is the default setting), we will delete the frameworks to maintain ground-truth in database.
        - name: RETAIN_MODE_ENABLED
{% if cluster_cfg['database-controller']['retain-mode'] %}
          value: "true"
{% else %}
          value: "false"
{% endif %}
         # If RBAC is set up in current environment.
         # If RBAC_IN_CLUSTER=true, the API Server client can read all settings automatically in container.
         # If RBAC_IN_CLUSTER=false, we should set CUSTOM_K8S_API_SERVER_URL.
{% if cluster_cfg['cluster']['common']['k8s-rbac'] != 'false' %}
        - name: RBAC_IN_CLUSTER
          value: "true"
{% else %}
        - name: RBAC_IN_CLUSTER
          value: "false"
        - name: CUSTOM_K8S_API_SERVER_URL
          value: {{ cluster_cfg['layout']['kubernetes']['api-servers-url'] }}
{% endif %}
        # The URL of write merger.
        - name: WRITE_MERGER_URL
          value: "{{ cluster_cfg['database-controller']['write-merger-url'] }}"
        # Max rpc concurrency for framework watcher
        - name: MAX_RPC_CONCURRENCY
          value: "{{ cluster_cfg['database-controller']['framework-watcher-max-rpc-concurrency'] }}"
        - name: WATCH_TIMEOUT_SECONDS
          value: "{{ cluster_cfg['database-controller']['framework-watcher-watch-timeout-seconds'] }}"
        command: ["node", "--max-old-space-size={{ cluster_cfg['database-controller']['framework-watcher-max-heap-mb'] }}", "watcher/framework/index.js"]
      - name: cluster-event-watcher
        image: {{ cluster_cfg["cluster"]["docker-registry"]["prefix"] }}database-controller:{{ cluster_cfg["cluster"]["docker-registry"]["tag"] }}
        imagePullPolicy: Always
        volumeMounts:
        - name: internal-data-dir
          mountPath: /paiInternal/storage
          readOnly: true
          mountPropagation: "None"
        env:
        # Log level of all logs. You can choose from error, warn, info, http, verbose, debug, and silly. Default value is info.
        - name: LOG_LEVEL
          value: "{{ cluster_cfg['database-controller']['log-level'] }}"
        # The global timeout for all calls to Kubernetes API server. Default value is 120.
        - name: K8S_CONNECTION_TIMEOUT_SECOND
          value: "{{ cluster_cfg['database-controller']['k8s-connection-timeout-second'] }}"
        # The timeout for calls to write merger. Default value is 120.
        - name: WRITE_MERGER_CONNECTION_TIMEOUT_SECOND
          value: "{{ cluster_cfg['database-controller']['write-merger-connection-timeout-second'] }}"
        # Whether to enable retain mode.
        # If someone submits a framework directly without accessing database, we can find the framework in write merger.
        # For these frameworks, if retain mode is on, we will ignore them.
        # If retain mode is off (it is the default setting), we will delete the frameworks to maintain ground-truth in database.
        - name: RETAIN_MODE_ENABLED
{% if cluster_cfg['database-controller']['retain-mode'] %}
          value: "true"
{% else %}
          value: "false"
{% endif %}
         # If RBAC is set up in current environment.
         # If RBAC_IN_CLUSTER=true, the API Server client can read all settings automatically in container.
         # If RBAC_IN_CLUSTER=false, we should set CUSTOM_K8S_API_SERVER_URL.
{% if cluster_cfg['cluster']['common']['k8s-rbac'] != 'false' %}
        - name: RBAC_IN_CLUSTER
          value: "true"
{% else %}
        - name: RBAC_IN_CLUSTER
          value: "false"
        - name: CUSTOM_K8S_API_SERVER_URL
          value: {{ cluster_cfg['layout']['kubernetes']['api-servers-url'] }}
{% endif %}
        # The database client string. It follows the format "<database type>://<user>:<password>@<host>:<port>/<database name>"
        - name: DB_CONNECTION_STR
          value: "{{ cluster_cfg['postgresql']['connection-str'] }}"
        # Max connection number to database in write merger. Default value is 10.
        - name: MAX_DB_CONNECTION
          value: "{{ cluster_cfg['database-controller']['db-poller-max-db-connection'] }}"
        # Max rpc concurrency for cluster event watcher
        - name: MAX_RPC_CONCURRENCY
          value: "{{ cluster_cfg['database-controller']['cluster-event-watcher-max-rpc-concurrency'] }}"
        - name: DISK_PATH
          value: "/paiInternal/storage"
        - name: MAX_DISK_USAGE_PERCENT
          value:  "{{ cluster_cfg['database-controller']['cluster-event-watcher-max-disk-usage-percent'] }}"
        - name: WATCH_TIMEOUT_SECONDS
          value: "{{ cluster_cfg['database-controller']['cluster-event-watcher-watch-timeout-seconds'] }}"
        command: ["node", "--max-old-space-size={{ cluster_cfg['database-controller']['cluster-event-watcher-max-heap-mb'] }}", "watcher/cluster-event/index.js"]
      - name: poller
        image: {{ cluster_cfg["cluster"]["docker-registry"]["prefix"] }}database-controller:{{ cluster_cfg["cluster"]["docker-registry"]["tag"] }}
        imagePullPolicy: Always
        env:
        # Log level of all logs. You can choose from error, warn, info, http, verbose, debug', and silly. Default value is info.
        - name: LOG_LEVEL
          value: "{{ cluster_cfg['database-controller']['log-level'] }}"
        # The global timeout for all calls to Kubernetes API server. Default value is 120.
        - name: K8S_CONNECTION_TIMEOUT_SECOND
          value: "{{ cluster_cfg['database-controller']['k8s-connection-timeout-second'] }}"
        # The timeout for calls to write merger. Default value is 120.
        - name: WRITE_MERGER_CONNECTION_TIMEOUT_SECOND
          value: "{{ cluster_cfg['database-controller']['write-merger-connection-timeout-second'] }}"
        # Whether to enable retain mode.
        # If someone submits a framework directly without accessing database, we can find the framework in write merger.
        # For these frameworks, if retain mode is on, we will ignore them.
        # If retain mode is off (it is the default setting), we will delete the frameworks to maintain ground-truth in database.
        - name: RETAIN_MODE_ENABLED
{% if cluster_cfg['database-controller']['retain-mode'] %}
          value: "true"
{% else %}
          value: "false"
{% endif %}
         # If RBAC is set up in current environment.
         # If RBAC_IN_CLUSTER=true, the API Server client can read all settings automatically in container.
         # If RBAC_IN_CLUSTER=false, we should set CUSTOM_K8S_API_SERVER_URL.
{% if cluster_cfg['cluster']['common']['k8s-rbac'] != 'false' %}
        - name: RBAC_IN_CLUSTER
          value: "true"
{% else %}
        - name: RBAC_IN_CLUSTER
          value: "false"
        - name: CUSTOM_K8S_API_SERVER_URL
          value: {{ cluster_cfg['layout']['kubernetes']['api-servers-url'] }}
{% endif %}
        # The database client string. It follows the format "<database type>://<user>:<password>@<host>:<port>/<database name>"
        - name: DB_CONNECTION_STR
          value: "{{ cluster_cfg['postgresql']['connection-str'] }}"
        # Max connection number to database in write merger. Default value is 10.
        - name: MAX_DB_CONNECTION
          value: "{{ cluster_cfg['database-controller']['db-poller-max-db-connection'] }}"
        # Polling interval of database poller. Default value is 120.
        - name: INTERVAL_SECOND
          value: "{{ cluster_cfg['database-controller']['db-poller-interval-second'] }}"
        # The URL of write merger.
        - name: WRITE_MERGER_URL
          value: "{{ cluster_cfg['database-controller']['write-merger-url'] }}"
        # Max rpc concurrency for db poller
        - name: MAX_RPC_CONCURRENCY
          value: "{{ cluster_cfg['database-controller']['db-poller-max-rpc-concurrency'] }}"
        command: ["node", "--max-old-space-size={{ cluster_cfg['database-controller']['db-poller-max-heap-mb'] }}", "poller/index.js"]
      volumes:
        - name: internal-data-dir
          hostPath:
            path: '{{ cluster_cfg["internal-storage"]["root-path"] }}/storage'
      imagePullSecrets:
      - name: {{ cluster_cfg["cluster"]["docker-registry"]["secret-name"] }}
